package com.supplychain.scm.core.common.version;

import com.supplychain.scm.core.common.version.config.ApiVersionProperties;
import com.supplychain.scm.core.common.version.enums.ClientType;
import com.supplychain.scm.core.common.version.enums.VersionSource;
import lombok.AllArgsConstructor;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.mvc.condition.RequestCondition;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.stream.Stream;

/**
 * @author liyang
 * @version 1.0.0
 * @ClassName ApiVersionRequestCondition
 * @createTime 12:11:00 2023/01/05
 */
@AllArgsConstructor
public class ApiVersionRequestCondition implements RequestCondition<ApiVersionRequestCondition> {

    private final ApiVersionProperties apiVersionProperties;

    private final ApiVersionItem apiVersionItem;

    /**
     * 将不同筛选条件合并
     *
     * @param other
     * @return
     */
    @Override
    public ApiVersionRequestCondition combine(ApiVersionRequestCondition other) {
        return other;
    }

    /**
     * 匹配
     *
     * @param request
     * @return
     */
    @Override
    public ApiVersionRequestCondition getMatchingCondition(HttpServletRequest request) {
        // 在请求中获取到指定版本
        String version = null;
        String clientType = null;
        VersionSource versionSource = apiVersionProperties.getVersionSource();
        if (versionSource != null) {
            String parameterName = apiVersionProperties.getParameterName();
            String clientTypeName = apiVersionProperties.getClientTypeName();
            switch (versionSource) {
                case HEADER:
                    version = request.getHeader(parameterName);
                    clientType = request.getHeader(clientTypeName);
                    break;
                case PARAMETER:
                    version = request.getParameter(parameterName);
                    clientType = request.getParameter(clientTypeName);
                    break;
                case COOKIE:
                    Cookie[] cookieArray = request.getCookies();
                    if(Objects.nonNull(cookieArray) && cookieArray.length > 0) {
                        for (Cookie cookie : cookieArray) {
                            if (Objects.equals(parameterName, cookie.getName())) {
                                version = cookie.getValue();
                                break;
                            }
                            if (Objects.equals(clientTypeName, cookie.getName())) {
                                clientType = cookie.getValue();
                                break;
                            }
                        }
                    }
                    break;
                case ALL:
                    version = request.getHeader(parameterName);
                    if (!StringUtils.hasText(version)) {
                        version = request.getParameter(parameterName);
                    }
                    if (!StringUtils.hasText(version)) {
                        Cookie[] cookies = request.getCookies();
                        if(Objects.nonNull(cookies) && cookies.length > 0) {
                            for (Cookie cookie : cookies) {
                                if (Objects.equals(parameterName, cookie.getName())) {
                                    version = cookie.getValue();
                                    break;
                                }
                            }
                        }
                    }
                    clientType = request.getHeader(clientTypeName);
                    if (!StringUtils.hasText(clientType)) {
                        clientType = request.getParameter(clientTypeName);
                    }
                    if (!StringUtils.hasText(clientType)) {
                        Cookie[] cookies = request.getCookies();
                        if(Objects.nonNull(cookies) && cookies.length > 0){
                            for (Cookie cookie : cookies) {
                                if (Objects.equals(clientTypeName, cookie.getName())) {
                                    clientType = cookie.getValue();
                                    break;
                                }
                            }
                        }
                    }
                    break;
                default:
                    break;
            }
        }
        if (StringUtils.hasText(clientType)) {
            ClientType value = ClientType.getClientType(clientType);
            if (value == null) {
                return null;
            }
            ClientType[] clientTypes = apiVersionItem.getClientTypes();
            if (Stream.of(clientTypes).noneMatch(c -> c == value)) {
                return null;
            }
        }
        // 当前版本和指定版本比较，当未指定版本时全部匹配 当指定版本时匹配等于或小于版本
        if (apiVersionItem.compareTo(ApiVersionItem.converter(version, null)) < 1) {
            return this;
        }
        return null;
    }

    /**
     * 比较 获取最大版本
     *
     * @param other
     * @param request
     * @return
     */
    @Override
    public int compareTo(ApiVersionRequestCondition other, HttpServletRequest request) {
        return other.apiVersionItem.compareTo(this.apiVersionItem);
    }
}
